<?php


namespace services\common;

use common\models\clinic\Clinic;
use common\models\common\Provinces;
use common\models\marketing\SourceChannel;
use Yii;
use common\helpers\ArrayHelper;
use common\helpers\CommonHelper;
use common\models\base\Project;
use common\models\base\Profession;
use common\models\base\PatientDiseases;
use common\models\common\Config;
use common\models\marketing\OutpatientType;
use common\models\marketing\Tags;
use common\models\marketing\TagsGroup;
use common\models\member\Attr;
use common\models\member\Member;
use common\components\Service;

class CommonService extends Service
{
    //1、获取用户列表
    //2、获取就诊类型列表
    //3、获取标签列表
    //4、获取病种列表


    /**
     * 用户绑定项目列表
     *
     * @param array $params
     * @return array
     */
    public static function getBindProjectList(array $params = []): array
    {
        // 用户ID
        $params['member_id'] = $params['member_id'] ?? Yii::$app->user->identity->member_id;
        // 用户信息
        $member = Member::findOne($params['member_id']);

        $query = Project::find()
            ->select(['id', 'name'])
            ->where([
                'status' => Project::STATUS_ENABLE,
            ]);
        if ($member && $member->is_super == Member::IS_SUPER_NO) {
            $attr = Attr::find()
                ->where(['member_id' => $member->id])
                ->asArray()
                ->all();

            $query->andWhere(['id' => array_column($attr, 'project_id')]);
        }

        return $query->asArray()->all();
    }

    /**
     * 获取就诊类型列表
     *
     * @param int|null $projectId 项目ID【null为当前项目】
     * @return array
     */
    public static function getOutpatientTypeList(?int $isCustomer = null): array
    {
        $select = ['id', 'outpatient_name AS name', 'status'];
        $query = OutpatientType::find()
            ->select($select)
            ->where([
                'status' => [OutpatientType::STATUS_ENABLE, OutpatientType::STATUS_INVALID],
            ]);

        if (is_null($isCustomer)) {
            $isCustomer = Yii::$app->params['is_customer'];
        }
        /*if (is_null($projectId)) {
            $projectId = Yii::$app->params['project_id'];
        }*/

        if ($isCustomer == 1) {// 客服
            $config = Yii::$app->services->config->findInfo([
                'config_name' => Config::CONFIG_NAME_CUSTOMER_OUTPATIENT,
                'project_id' => Yii::$app->params['project_id'],
            ]);
            $ids = [];
            if ($config && $config->config_value) {
                $ids = explode(',', $config->config_value);
            }

            return $query
                ->andWhere(['id' => $ids])
                ->asArray()
                ->all();
        }

        return $query->asArray()->all();
    }

    /**
     * 获取标签列表
     *
     * @return array
     */
    public static function getTagsList(): array
    {
        $marketingTagsList = Tags::find()
            ->select(['id', 'tags_name AS name', 'tags_group_id', 'status'])
            ->where([
                'project_id' => Yii::$app->params['project_id'],
                'status' => [Tags::STATUS_ENABLE, Tags::STATUS_INVALID],
            ])
            ->asArray()
            ->all();

        $marketingTagsGroupList = TagsGroup::find()
            ->select(['id', 'group_name AS name'])
            ->where([
                'id' => array_column($marketingTagsList, 'tags_group_id'),
            ])
            ->asArray()
            ->all();

        $tagsList = [];
        foreach ($marketingTagsList as $row) {
            $tagsList[$row['tags_group_id']][] = [
                'id' => $row['id'],
                'name' => $row['name'],
                'status' => $row['status'],
            ];
        }

        $list = [];
        foreach ($marketingTagsGroupList as $row) {
            $list[] = [
                'id' => $row['id'],
                'name' => $row['name'],
                'children' => $tagsList[$row['id']],
            ];
        }

        return $list;
    }

    /**
     * 获取病种列表
     *
     * @param int|null $pid
     * @param null $status
     * @return array
     */
    public static function getDiseasesList(?int $pid = 0, $status = null, $noDiseases = 0): array
    {
        $query = PatientDiseases::find()
            ->select(['id', 'diseases_name AS name', 'status'])
            ->where([
                'status' => [PatientDiseases::STATUS_ENABLE, PatientDiseases::STATUS_INVALID],
            ]);

        if (!is_null($pid)) {
            $query->andWhere(['pid' => $pid]);
        }

        $list = $query->asArray()->all();
        if ($noDiseases == 1) {
            array_unshift($list, ['id' => 0, 'name' => '无病种', 'status' => PatientDiseases::STATUS_ENABLE]);
        }
        return $list;
    }

    /**
     * 获取归属人列表
     *
     * @param int $type 类型【默认所有、1客服归属人、2医助归属人、3客服+医助】
     * @param int $isFormat 格式化【0原样返回、1岗位=>人员】
     * @return array
     */
    public static function getMemberList(int $type = 0, int $isFormat = 0): array
    {
        // 用户属性列表
        $queryAttr = Attr::find()
            ->select(['*'])
            ->where([
                'project_id' => Yii::$app->params['project_id'],
            ]);

        // 岗位
        $professionIds = [];
        switch ($type) {
            case 1:
                $professionIds = Profession::ID_CUSTOMER;
                $queryAttr->andWhere(['profession_id' => $professionIds]);
                break;
            case 2:
                $professionIds = Profession::ID_MEDICAL;
                $queryAttr->andWhere(['profession_id' => $professionIds]);
                break;
            case 3:
                $professionIds = [Profession::ID_CUSTOMER, Profession::ID_MEDICAL];
                $queryAttr->andWhere(['profession_id' => $professionIds]);
                break;
            default:
                break;
        }

        $memberIds = [];
        if (Yii::$app->params['is_department_leader'] == Attr::IS_DEPARTMENT_LEADER_NO) {// 普通员工【自己】
            $queryAttr->andWhere(['member_id' => Yii::$app->user->identity->member_id]);
//            $memberIds = [Yii::$app->user->identity->member_id];
        } elseif (Yii::$app->params['is_department_leader'] == Attr::IS_DEPARTMENT_LEADER_YES) {// 部门负责人【部门下所有员工】
            $queryAttr->andWhere(['department_id' => Yii::$app->params['department_id']]);
        } else {// 项目负责人【项目下员工】

        }
        $attrList = $queryAttr
            ->indexBy('member_id')
            ->asArray()
            ->all();
//        if (Yii::$app->params['is_department_leader'] != Attr::IS_DEPARTMENT_LEADER_NO) {
            $memberIds = array_column($attrList, 'member_id');
//        }

        $memberList = Member::find()
            ->select(['id', 'realname AS name'])
            ->where([
                'id' => $memberIds,
                'status' => Member::STATUS_ENABLE
            ])
            ->asArray()
            ->all();

        if ($isFormat == 1) {// 格式化【岗位 => 人员】
            $professionList = Profession::find()
                ->select(['id', 'name'])
                ->where(['id' => $professionIds])
                ->asArray()
                ->all();

            foreach ($professionList as $key => $row) {
                $professionList[$key]['children'] = [];

                foreach ($memberList as $val) {
                    $attr = $attrList[$val['id']] ?? [];
                    if ($attr && $attr['profession_id'] == $row['id']) {
                        $professionList[$key]['children'][] = $val;
                    }
                }
            }

            return $professionList;
        }

        return $memberList;
    }

    /**
     * @apiName
     * @apiGroup
     */
    public static function getClinicList()
    {
       $clinicList = Clinic::find()
           ->select(['id as value','name as label'])
            ->where([
                'status' => Clinic::STATUS_ENABLE,
                'project_id' => Yii::$app->params['project_id']
            ])
            ->asArray()
            ->all();

       return $clinicList;
    }

    /**
     * 申请全局排他锁
     * @param string $name 锁名称
     * @param int $ttl 锁失效时间，避免死锁
     * @param bool $should_block 是否阻塞，非阻塞锁获取失败即返回，阻塞锁会反复申请直到成功
     * @throws GusException
     * @return boolean
     */
    public static function acquire_global_lock($name, $should_block = false){

        $redis = Yii::$app->redis;

        // 锁失效时间
        $ttl = Yii::$app->params['user.route_time'];

        if(!is_string($name)){
            throw new GusException('全局锁名称必须为字符串');
        }
        $name = trim($name);
        if(empty($name)){
            throw new GusException('全局锁名称不能为空');
        }
        if(!is_int($ttl) || $ttl < 1){
            throw new GusException('全局锁生存时间必须为正整数');
        }
        $lock = "PUAS_GLOBAL_LOCK_{$name}";
        while(true){
            $expire = time() + $ttl + 1;
            $ret = $redis->setnx($lock, $expire);
            // 获取失败
            if($ret == 0){
                // 阻塞锁
                $old_expire = $redis->get($lock);
                $sleep = $old_expire - time();
                if($sleep > 0){
                    if($should_block){
                        sleep(rand(1, $sleep));
                        continue;
                    } else{
                        // 非阻塞锁，直接失败
                        return false;
                    }
                } else{
                    $new_expire = $redis->getset($lock, time() + $ttl + 1);
                    if($new_expire != $old_expire){
                        continue;
                    }
                }
            }
            // 获取成功
            break;
        }
        // 脚本结束时，释放锁
        register_shutdown_function(
            function ($expire, $lock){
                // 如果锁没过期，主动释放，否则不应释放避免已被其他进程锁定
                $redis = Yii::$app->redis;
                if(time() > $expire){
                    $redis->del($lock);
                }
            }, $expire, $lock);
        return true;
    }
    /**
     * 释放全局锁
     * @param string $name
     */
    public static function release_global_lock($name){
        $redis = Yii::$app->redis;
        $redis->del("PUAS_GLOBAL_LOCK_{$name}");
    }

    // 根据ip地址,转化位置
    public static function getIpLocation($ip)
    {
        $data_ip = CommonHelper::https_request(Yii::$app->params['ipRegionUrl'], ['ip' => $ip]);
        $ret = json_decode($data_ip, true);
        if ($ret && isset($ret['data'])) {
            $ipAddress = $ret['data']['city'] ?? '';
        } else {
            $ipAddress = '';
        }

        return $ipAddress;

    }

    /**
     * 时间格式转成 年-月-日 星期几 时:分
     * @return void
     */
    public static function timeChangeWeek($timestamp) :string
    {
        $weekMap = [
            "日", "一", "二", "三", "四", "五", "六"
        ];

        $createDate = $timestamp ? date('Y-m-d H:i', $timestamp) : '';
        if ($timestamp) {
            $weekNum = date('w', $timestamp);
            list($year, $hour) = explode(' ', $createDate);
            $createDate = "{$year} 周{$weekMap[$weekNum]} $hour";
        }

        return $createDate;
    }

    /**
     * 映射表缓存
     * @param string $key 切换数据表(表base_ 后面的值)
     * @param int $type 1 = get  2 = update
     * @return array
     */
    public static function baseRedis(string $key, int $type = 1): array
    {
        $redisKey = 'byBase:' . $key;
        $redis = Yii::$app->redis;
        if ($type == 2) {
            $redis->del($redisKey);
            return [];
        }

        $resultStr = $redis->get($redisKey);
        if (empty($resultStr)) {
            if ($key == 'clinic') {
                $query = Clinic::find();
            } elseif ($key == 'patient_diseases') {
                $query = PatientDiseases::find();
            } elseif ($key == 'source_channel') {
                $query = SourceChannel::find();
            } elseif ($key == 'out_patient_type') {
                $query = OutpatientType::find();
            } elseif ($key == 'member') {
                $query = Member::find()->select('id,realname,status,is_super,username,mobile');
            } else {
                return [];
            }

            $indexBy = "id";
            $result = $query->indexBy($indexBy)->asArray()->all();

            $resultStr = json_encode($result);
            $redis->set($redisKey, $resultStr);
            $redis->expire($redisKey, 86400 * 7);
        }

        return json_decode($resultStr, true);
    }
}
